package com.ljx.recruitment.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljx.recruitment.common.domain.vo.resp.CommonTextResp;
import com.ljx.recruitment.common.domain.vo.resp.PageResp;
import com.ljx.recruitment.common.enums.CommonStatusTypeEnum;
import com.ljx.recruitment.common.exception.ApiException;
import com.ljx.recruitment.interview.domain.entity.JobLocation;
import com.ljx.recruitment.interview.domain.entity.JobType;
import com.ljx.recruitment.interview.enums.JobKindEnum;
import com.ljx.recruitment.interview.service.JobLocationService;
import com.ljx.recruitment.interview.service.JobTypeService;
import com.ljx.recruitment.interview.service.ResumeService;
import com.ljx.recruitment.security.util.UserUtil;
import com.ljx.recruitment.user.domain.dto.UserFlagDto;
import com.ljx.recruitment.user.domain.entity.Tenant;
import com.ljx.recruitment.user.domain.entity.User;
import com.ljx.recruitment.user.domain.vo.req.TenantPageReq;
import com.ljx.recruitment.user.domain.vo.req.TenantSubmitReq;
import com.ljx.recruitment.user.domain.vo.req.UserPageReq;
import com.ljx.recruitment.user.domain.vo.resp.*;
import com.ljx.recruitment.user.enums.ImageKeyEnum;
import com.ljx.recruitment.user.enums.SearchFilterEnum;
import com.ljx.recruitment.user.enums.TenantMenuEnum;
import com.ljx.recruitment.user.enums.ThemeEnum;
import com.ljx.recruitment.user.event.TenantSubmitEvent;
import com.ljx.recruitment.user.mapper.TenantMapper;
import com.ljx.recruitment.user.service.MenuService;
import com.ljx.recruitment.user.service.TenantService;
import com.ljx.recruitment.user.service.UserService;
import com.ljx.recruitment.user.typehandler.details.ResumeDetails;
import com.ljx.recruitment.user.typehandler.details.ThemeDetails;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-10-31  13:38
 */
@Service
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService {

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private ResumeService resumeService;

    @Autowired
    private JobLocationService jobLocationService;

    @Autowired
    private JobTypeService jobTypeService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public TenantResp getInfoByCode(String code) {
        Tenant tenant = tenantMapper.selectOne(new LambdaQueryWrapper<Tenant>()
                .eq(Tenant::getCode, code)
                .eq(Tenant::getStatus, CommonStatusTypeEnum.NORMAL.getKey()));
        if (Objects.isNull(tenant)) {
            throw new ApiException("租户不存在");
        }
        return BeanUtil.copyProperties(tenant, TenantResp.class);
    }

    @Override
    public PageResp<User> getUserPage(UserPageReq req) {
        Boolean isTenantAdmin = UserUtil.checkIsTenantAdmin();
        Boolean isSuperUser = UserUtil.checkIsPlatformAdmin();
        if (!isTenantAdmin && !isSuperUser){
            throw new ApiException("权限不足");
        }

        UserService userService = SpringUtil.getBean(UserService.class);
        return userService.getPage(req, new UserFlagDto(isTenantAdmin, isSuperUser));
    }

    @Override
    @Transactional
    public TenantResp submit(TenantSubmitReq req) {
        Tenant tenant;
        if (Objects.isNull(req.getId())){
            checkSubmitSaveParams(req);
            tenant = BeanUtil.copyProperties(req, Tenant.class);
            initTenant(tenant);
            tenantMapper.insert(tenant);
            applicationEventPublisher.publishEvent(new TenantSubmitEvent(this, tenant.getId()));
        } else {
            checkSubmitUpdateParams(req);
            tenant = tenantMapper.selectById(req.getId());
//            copyReqParamsToTenant(req, tenant);
            BeanUtils.copyProperties(req, tenant);
            tenantMapper.updateById(tenant);
        }
        return getInfo(tenant.getId());
    }

    private void checkSubmitSaveParams(TenantSubmitReq req) {
        if (StrUtil.isEmpty(req.getCode()) || StrUtil.isEmpty(req.getName())){
            throw new ApiException("必要参数不能为空");
        }
        if (!UserUtil.checkIsPlatformAdmin()){
            throw new ApiException("权限不足");
        }
    }

    private void checkSubmitUpdateParams(TenantSubmitReq req) {
        if (Objects.nonNull(req.getId()) && !req.getId().equals(UserUtil.tryToGetTenantId())) {
            throw new ApiException("权限不足");
        }
        if (Objects.isNull(req.getId())){
            req.setId(UserUtil.tryToGetTenantId());
        }
    }

    private void initTenant(Tenant tenant) {
        ThemeDetails themeDetails = new ThemeDetails();
        themeDetails.putAll(ImageKeyEnum.getCacheMap());
        themeDetails.putAll(ThemeEnum.getCacheMap());
        themeDetails.put(ThemeEnum.MENUS.getKey(), menuService.init());
        tenant.setThemeDetails(themeDetails);
        tenant.setResumeDetails(new ResumeDetails(resumeService.init()));
    }

    @Override
    public PageResp<Tenant> getPage(TenantPageReq req) {
        LambdaQueryWrapper<Tenant> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(req.getKey())){
            lambdaQueryWrapper.like(Tenant::getName, req.getKey());
        }
        Page<Tenant> page = tenantMapper.selectPage(new Page<>(req.getCurrPage(), req.getPageSize()), lambdaQueryWrapper);
        return PageResp.<Tenant>builder()
                .list(page.getRecords())
                .total(page.getTotal())
                .build();
    }

    @Override
    public TenantResp getInfo(Long tenantId) {
        Tenant tenant = tenantMapper.selectById(tenantId);
        return BeanUtil.copyProperties(tenant, TenantResp.class);
    }

    @Override
    public TenantResp refreshResume(Long tenantId) {
        Tenant tenant = tenantMapper.selectById(tenantId);
        tenant.setResumeDetails(new ResumeDetails(resumeService.refresh()));
        tenantMapper.updateById(tenant);

        return getInfo(tenantId);
    }

    @Override
    public List<TenantSearchFilterResp> getSearchFilter(Long tenantId) {
        List<TenantSearchFilterResp> res = new ArrayList<>();

        List<CommonTextResp> jobLocations = jobLocationService.list(new LambdaQueryWrapper<JobLocation>()
                .eq(JobLocation::getTenantId, tenantId)
                .eq(JobLocation::getStatus, CommonStatusTypeEnum.NORMAL.getKey()))
                .stream()
                .map(item -> new CommonTextResp(item.getId(), item.getName()))
                .collect(Collectors.toList());
        res.add(new TenantSearchFilterResp(SearchFilterEnum.LOCATION.getKey(), SearchFilterEnum.LOCATION.getValue(), jobLocations));

        List<CommonTextResp> jobTypes = jobTypeService.list(new LambdaQueryWrapper<JobType>()
                        .eq(JobType::getTenantId, tenantId)
                        .eq(JobType::getStatus, CommonStatusTypeEnum.NORMAL.getKey()))
                .stream()
                .map(item -> new CommonTextResp(item.getId(), item.getName()))
                .collect(Collectors.toList());
        res.add(new TenantSearchFilterResp(SearchFilterEnum.TYPE.getKey(), SearchFilterEnum.TYPE.getValue(), jobTypes));

        List<CommonTextResp> jobKinds = new ArrayList<>();
        jobKinds.add(new CommonTextResp(Long.parseLong(JobKindEnum.FULL_TIME.getKey().toString()), JobKindEnum.FULL_TIME.getDesc()));
        jobKinds.add(new CommonTextResp(Long.parseLong(JobKindEnum.INTERNSHIP.getKey().toString()), JobKindEnum.INTERNSHIP.getDesc()));
        res.add(new TenantSearchFilterResp(SearchFilterEnum.KIND.getKey(), SearchFilterEnum.KIND.getValue(), jobKinds));

        return res;
    }

    @Override
    public List<ThemeConfigResp> getThemeConfigList() {
        List<ThemeConfigResp> result = new ArrayList<>();
        for (ImageKeyEnum item : ImageKeyEnum.values()) {
            result.add(new ThemeConfigResp(item.getKey(), item.getDesc()));
        }
        for (ThemeEnum item : ThemeEnum.values()) {
            result.add(new ThemeConfigResp(item.getKey(), item.getDesc()));
        }

        return result;
    }

    @Override
    public List<NavItemResp> getSiteNavList() {
        Tenant tenant = tenantMapper.selectById(UserUtil.tryToGetTenantId());
        return JSONUtil.toList(tenant.getThemeDetails().get(ThemeEnum.MENUS.getKey()).toString(), NavItemResp.class)
                .stream()
                .map(item -> {
                    if (item.getKey().equals(TenantMenuEnum.ADMIN.getKey())) {
                        item.setDisplay(Objects.nonNull(UserUtil.getUserInfo()) &&
                                ((UserUtil.checkIsTenantAdmin()) || UserUtil.checkIsHr() ));
                    }
                    return item;
                }).collect(Collectors.toList());
    }
}
